package com.wolfking.sharding.controller;

import com.google.common.collect.Maps;
import com.wolfking.sharding.config.DataSourceConfig;
import com.wolfking.sharding.seq.UserGatherSeqService;
import lombok.SneakyThrows;
import org.apache.shardingsphere.transaction.annotation.ShardingSphereTransactionType;
import org.apache.shardingsphere.transaction.core.TransactionType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

@Controller
@RequestMapping("/crud")
public class CrudController implements CommandLineRunner {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @ResponseBody
    @RequestMapping("/inserta")
    public Object insertA() {
        jdbcTemplate.update("insert into t_a(`id`,`name`) values (?,?)",
                UUID.randomUUID().toString().replace("-", ""), "ximenqing");

        return "{}";
    }

    @ResponseBody
    @RequestMapping("/insertb")
    public Object insertB() {
        jdbcTemplate.update("insert into t_b(`id`,`name`) values (?,?)",
                UUID.randomUUID().toString().replace("-", ""), "panjinglian");
        return "{}";
    }

    @ResponseBody
    @Transactional
    @RequestMapping("/insertall")
    @ShardingSphereTransactionType(TransactionType.XA)
    public Object insertall() {
        jdbcTemplate.update("insert into t_all(`id`,`source`) values (?,?)",
                UUID.randomUUID().toString().replace("-", ""), "a");
        jdbcTemplate.update("insert into t_all(`id`,`source`) values (?,?)",
                UUID.randomUUID().toString().replace("-", ""), "b");
        return "{}";
    }

    @ResponseBody
    @RequestMapping("/selectall")
    public Object selectall() {

        try {

            List<Map<String, Object>> maps = jdbcTemplate.queryForList("select * from t_all where source = 'a'");
            List<Map<String, Object>> maps1 = jdbcTemplate.queryForList("select * from t_all where source = 'b'");

            return jdbcTemplate.queryForList("select * from t_all");
        } finally {
            DataSourceConfig.clearDataSourceType();
        }
    }

    @ResponseBody
    @RequestMapping("/masterSlave")
    public Object masterSlave() {

        try {
            List<Map<String, Object>> maps = jdbcTemplate.queryForList("select * from sql_define");
            DataSourceConfig.setDataSourceType("slave");
            maps = jdbcTemplate.queryForList("select * from sql_define");
            return jdbcTemplate.queryForList("select * from t_all");
        } finally {
            DataSourceConfig.clearDataSourceType();
        }
    }

    @Autowired
    private UserGatherSeqService userGatherSeqService;

    @ResponseBody
    @SneakyThrows
    @RequestMapping("/table_seq")
    public Object tableSeq() {
        ThreadPoolExecutor executor = new ThreadPoolExecutor(100, 100, 10, TimeUnit.SECONDS, new ArrayBlockingQueue<>(100),
                new ThreadPoolExecutor.CallerRunsPolicy());
        CountDownLatch countDownLatch = new CountDownLatch(100);
        for (int i = 0; i < 100; i++) {
            executor.execute(() -> {
                try {
                    for (int j = 0; j < 1000; j++) {
                        userGatherSeqService.getNextId();
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    countDownLatch.countDown();
                }
            });
        }
        countDownLatch.await();
        executor.shutdown();
        return Maps.newHashMap();
    }

    @Override
    public void run(String... args) throws Exception {
        System.out.println("");
    }
}
